#!/usr/bin/env python
#coding=utf-8
# author:wade
# contact: 317909531@qq.com
# datetime:2020/4/27 18:29

"""
文件说明：实现批量更新功能需要的知识
"""
from rest_framework import serializers
from rest_framework.views import APIView

from shareAPI import models
from shareAPI.views import APIResponse

"""
#1.序列化的故事
序列化类的功能就像一个时空飞梭，负责把三个人从一个规则世界（数菊酷的（高级）世界）解释道另外一个规则世界（json金神（低级）世界），这个就叫做序列化
反序列化的故事
只有老家在数菊酷的人才可以乘坐时空飞梭

#####################################
# 正题来了： 怎么解决批量更新的序列化呢？#
#####################################

三个金神世界的异能者接到任务需要穿越到 数据库世界，当然需要一个趁手的穿越器，
当然，这次三个人手里还带着需要修改的数据
第一：穿越机一次只能携带一个人，怎么办呢？经过改进，我们给他的车上升级加长版座位，ListSerializer（我能带1000人你信不），
#####################################
#               序列化车间           #
#####################################
"""

#下面这个是我们的“加长版座位”，ListSerializer的存在让穿越移民变成了可能，一辆车能把金神世界的人都给带去数据库世界
class B_Score_NoDepth_ListSerialzer(serializers.ListSerializer):
    def update(self, instance, validated_data):
        """
        :param instance: [book_obj1, ..., book_obj2]
        :param validated_data: [{更新数据的字段}, ..., {更新数据的字段}]
        :return: [book_new_obj1, ..., book_new_obj2]
        """
        for index, obj in enumerate(instance):   # type :int, models.Score
            # 单个对象数据更新 - 一个个属性更新值
            for attr, value in validated_data[index].items():
                # 对象有更新数据字典的key对应的属性，才完成该属性的值更新
                if hasattr(obj, attr):
                    setattr(obj, attr, value)
            # 信息同步到数据库
            obj.save()
        return instance


# 这个就是原版穿梭机，上边的是升级组件
class B_Score_NoDepth_Serializers(serializers.ModelSerializer):
    class Meta:
        model = models.Score
        fields = '__all__'
        # fields = ['CLASS_NUM', 'ID']
        list_serializer_class = B_Score_NoDepth_ListSerialzer  # 这就是新装备 ListSerialzer
    # def validate(self, attrs): 对 对象进行验证
    # def validate_xxx字段名(self,value): #对字段进行验证


"""
###################################################
#            ViewSet空间站                         #
#  queryset=>searlizer(querset,data=requset.data) #
#                                                 #
#      如果有queryset就是修改，如果没有就是增加       #
###################################################

"""
class Account(APIView):
    authentication_classes = []
    #批量修改功能
    def put(self, request, *args, **kwargs):

        """要使用可写嵌套序列化，您需要在序列化程序类上声明嵌套字段，并显式编写create（）和/或update（）方法。 """
        print("打印json提交的内容", request.data)  # 用json格式提交会得到<class 'dict'>格式
        # 更新的时候，看分享ID
        if isinstance(request.data, dict):
            # 单增 自定义验证，提交的信息是否在表格中
            queryset = models.Score.objects.filter(fenxiangid=request.data.get('fenxiangid')).first()
            if not queryset:
                return APIResponse(0, msg='fenxiangid不存在')
            else:
                print('fenxiangid存在,继续反序列化')
                # 单增
                # print('单条更新,需要一个查询实例queryset作为instance，用来给序列化做内容定位，data是用来修改字段的')
            serializer = B_Score_NoDepth_Serializers(queryset,data=request.data)  # 不带实例instance是create，序列化类不能是多个序列化嵌套类，有外键关系的可以通用
            serializer.is_valid(raise_exception=True)  # 如果校验失败，会直接抛异常，返回给前台

            print(serializer.validated_data)
            print(repr(serializer))

            obj = serializer.save()  # 返回一个数据库对象实例
            return APIResponse(result=serializer.data, msg=f"分享id：[{obj.fenxiangid}]修改成功")
        elif isinstance(request.data, list):

            print('批量修改，有不符合的列表单元会被丢弃')  # 批量修改
            try:
                pks = []  # 记录修改的表的主键值
                for dic in request.data:
                    pks.append(dic.get('fenxiangid'))
                data = request.data
                print('pks:', pks)
            except:
                return APIResponse(1, msg=f"列表内的数据中缺少 fenxiangid 主键字段")

            querySet_List = [] #  查询机 列表，用户传递给序列化 指明 是序列化哪一位异能者
            updata_Data_List = []   #需要更新的字段数据
            # 将提交的list中不存在的主键item剔除
            for index, pk in enumerate(pks):
                scoreOBJ = models.Score.objects.filter(pk=pk).first()
                if scoreOBJ:  #通过查询数菊酷世界数据，竟然有一个在数菊酷没记录，奶奶的，不是数菊酷世界高等生物，滚粗去
                    querySet_List.append(scoreOBJ)
                    updata_Data_List.append(data[index])
                    print('querySet_List', querySet_List)
                    print('updata_Data_List', updata_Data_List)
                else:
                    print("扔掉垃圾信息，滚，妈的，还长脸了？")
            # 反序列化完成数据的修改（开始上传，时空穿梭）
            score_ser = B_Score_NoDepth_Serializers(instance=querySet_List,
                                                                     data=updata_Data_List, many=True, partial=True)
            if score_ser.is_valid():
                result_obj_List = score_ser.save()   #save本来返回一个实例化对象，在批量的状态下返回一个实例化对象列表

                return APIResponse(results=B_Score_NoDepth_Serializers(result_obj_List, many=True).data)
            else:
                return APIResponse(1, msg=f"更新失败")

        else:
            return APIResponse(1, msg=f"批量修改格式错误")